package com.fisherman.config;

import com.fisherman.bean.Color;
import com.fisherman.bean.ColorFactoryBean;
import com.fisherman.bean.Person;
import com.fisherman.bean.Red;
import com.fisherman.condition.DuanCondition;
import com.fisherman.condition.FishermanCondition;
import com.fisherman.condition.MyImportBeanDefinitionRegistrar;
import com.fisherman.condition.MyImportSelector;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.*;

/**
 * @User: fisherman
 * @Date: 2020/5/18 11:54
 */
//类中组件统一设置  满足当前条件，这个类中配置的所有bean注册才能生效
@Conditional({DuanCondition.class})
@Configuration  //告诉spring这是个配置类
//@Import(Color.class)  //快速导入组件，id默认的是组件的全名  导单个的格式
@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig2 {

    //默认是单实例的

    /**
     * @see ConfigurableBeanFactory#SCOPE_PROTOTYPE  取值 prototype
     * @see ConfigurableBeanFactory#SCOPE_SINGLETON  取值 singleton
     * @see org.springframework  web.context.WebApplicationContext#SCOPE_REQUEST  取值 request
     * @see org.springframework  web.context.WebApplicationContext#SCOPE_SESSION  取值 session
     * <p>
     * <p>
     *
     *@Scope：调整作用域
     * prototype ： 多实例的,ioc容器启动并不会去调用方法创建对方放容器中，
     *              每次获取的时候才会调用方法创建对象
     * singleton : 单实例的（默认值），ioc容器启动会调用方法创建对象ioc容器中
     * 以后每次获取就是直接从容器（map.get()）中拿
     * request : 同一个请求创建一个实例
     * session ： 同一个session创建一个实例
     *
     *
     * 懒加载
     *      单实例bean，默认再容器启动的时候创建对象
     *      懒加载，容器启动不创建对象，第一次使用（获取）bean创建对象，并初始化
     */
//    @Scope("prototype")
    @Lazy
    @Bean("person")  //加到容器中
    public Person person() {
        System.out.println("给容器添加Person。。");
        return new Person("fisherman", 24);
    }

    /**
     * @Conditional({Condition})   按照一定的条件进行判断，满足条件给容器注册bean
     *
     * 如果是windows，给容器注册("fisherman")
     * 如果是linux系统，给容器中注册("fisherman1")
     */

    @Conditional({DuanCondition.class})
    @Bean("fisherman")
    public Person person01(){
        return new Person("fisherman",25);
    }

    @Conditional({FishermanCondition.class})
    @Bean("fisherman1")
    public Person person02(){
        return new Person("fisherman1",1);
    }

    /**
     * 给容器中注册组件
     * 1.包扫描+组件标注注解（@Controller/@Service/@Repository/@Component）[自己写的]
     * 2.@Bean【导入第三方包的组件】
     * 3.@Import 【快速给容器中导入组件】
     *      1.@Import(要导入到容器的组件)，容器中就会自动注册这个组件，id是默认全类名
     *      2.ImportSelector:返回需要导入的组件的全类名数组
     *      3.ImportBeanDefinitionRegistrar:它里面有个方法叫registerBeanDefinitions，通过调用这个方法可以自己给容器添加组件，
     *              AnnotationMetadata  当前类的一直注解信息
     *              BeanDefinitionRegistry  Bean定义的注册类
     *4.使用Spring提供的FactoryBean(工厂bean)
     *      1.默认获取到的是工厂bean调用getObject创建对象
     *      2.要获取工厂bean本身，我们需要给id前面加一个&
     *      &colorFactoryBean
     */
    @Bean
    public ColorFactoryBean colorFactoryBean(){
        return new ColorFactoryBean();
    }

}
